package org.zjx.window.window;

import com.sun.jna.platform.win32.WinDef;
import org.zjx.command.state.StateManager;
import org.zjx.window.action.IAction;
import org.zjx.window.operation.OperationExecutor;
import org.zjx.window.operation.WindowOperation;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 窗口接口
 * 定义窗口的基本操作和行为，包括激活、执行动作、状态管理等
 *
 * @author zjx
 * @since 1.0
 */
public interface IWindow {

    // ========== 基本属性 ==========

    /**
     * 获取窗口名称
     * 用于标识和日志记录
     *
     * @return 窗口名称，不会返回null
     */
    String getName();

    /**
     * 获取窗口句柄
     * 用于底层窗口操作
     *
     * @return 窗口句柄
     */
    WinDef.HWND getHwnd();

    /**
     * 获取窗口标题
     *
     * @return 窗口标题文本
     */
    String getTitle();

    /**
     * 检查窗口是否存在
     *
     * @return 如果窗口存在返回true，否则返回false
     */
    boolean isExists();

    /**
     * 获取窗口边界（包含标题栏和边框）
     *
     * @return 窗口边界矩形
     */
    Rectangle getBounds();

    /**
     * 获取窗口真实边界（仅客户区）
     *
     * @return 窗口客户区边界矩形
     */
    Rectangle getTrueBounds();

    // ========== 窗口操作 ==========

    /**
     * 激活窗口（置于前台）
     */
    void activate();

    /**
     * 检查窗口是否处于激活状态
     *
     * @return 如果窗口激活返回true，否则返回false
     */
    boolean isActive();

    /**
     * 等待窗口激活
     *
     * @param timeoutMs 超时时间（毫秒）
     * @return 如果在超时时间内激活返回true，否则返回false
     * @throws IllegalArgumentException 如果timeoutMs为负数
     */
    boolean waitForActive(long timeoutMs);

    /**
     * 关闭窗口
     */
    void close();

    // ========== 状态管理 ==========

    /**
     * 获取状态管理器
     *
     * @return 状态管理器实例
     */
    StateManager getState();

    /**
     * 更新窗口状态
     * 从实际窗口更新状态信息
     */
    void updateState();
    // ========== 界面截屏操作 ==========

    BufferedImage getScreenshot();

    void flushScreenshot();

    // ========== 动作执行 ==========

    /**
     * 提交动作到执行队列（异步）
     *
     * @param action 要执行的动作
     * @return 异步执行结果Future
     * @throws IllegalArgumentException 如果action为null
     */
    CompletableFuture<Boolean> submitAction(IAction action);

    /**
     * 立即执行动作（同步）
     *
     * @param action 要执行的动作
     * @throws IllegalArgumentException 如果action为null
     */
    void executeAction(IAction action);

    /**
     * 执行窗口操作
     *
     * @param operation 要执行的操作
     * @throws IllegalArgumentException 如果operation为null
     */
    void execute(WindowOperation operation);

    /**
     * 获取操作执行器
     *
     * @return 操作执行器实例
     */
    OperationExecutor getExecutor();

    // ========== 快捷操作方法 ==========

    /**
     * 顺序执行多个窗口操作
     *
     * @param operations 要执行的操作序列
     * @throws IllegalArgumentException 如果operations为null
     */
    default void executeSequence(WindowOperation... operations) {
        execute(WindowOperation.sequence(operations));
    }

    /**
     * 在窗口内指定坐标点击（左键）
     *
     * @param x 窗口内相对X坐标
     * @param y 窗口内相对Y坐标
     */
    default void clickAt(int x, int y) {
        executeSequence(
                WindowOperation.gameMove(x, y),
                WindowOperation.delay(30),
                WindowOperation.click(1)
        );
    }

    /**
     * 在窗口内指定坐标点击（左键，双精度版本）
     *
     * @param x 窗口内相对X坐标
     * @param y 窗口内相对Y坐标
     */
    default void clickAt(double x, double y) {
        clickAt((int) x, (int) y);
    }

    /**
     * 在窗口内指定区域内随机点击
     *
     * @param area 点击区域
     * @throws IllegalArgumentException 如果area为null
     */
    default void clickIn(Rectangle area) {
        executeSequence(
                WindowOperation.gameMove(area),
                WindowOperation.delay(30),
                WindowOperation.click(1),
                WindowOperation.delay(30)
        );
    }

    /**
     * 在当前鼠标位置点击（左键）
     */
    default void click() {
        executeSequence(
                WindowOperation.delay(30),
                WindowOperation.click(1),
                WindowOperation.delay(30)
        );
    }

    /**
     * 移动鼠标到窗口内指定坐标
     *
     * @param x 窗口内相对X坐标
     * @param y 窗口内相对Y坐标
     */
    default void moveTo(int x, int y) {
        execute(WindowOperation.gameMove(x, y));
    }

    /**
     * 移动鼠标到窗口内指定坐标（双精度版本）
     *
     * @param x 窗口内相对X坐标
     * @param y 窗口内相对Y坐标
     */
    default void moveTo(double x, double y) {
        moveTo((int) x, (int) y);
    }

    /**
     * 移动鼠标到窗口内指定区域内的随机位置
     *
     * @param area 移动区域
     * @throws IllegalArgumentException 如果area为null
     */
    default void moveTo(Rectangle area) {
        execute(WindowOperation.gameMove(area));
    }

    /**
     * 输入文本
     *
     * @param text 要输入的文本
     * @throws IllegalArgumentException 如果text为null
     */
    default void input(String text) {
        execute(WindowOperation.type(text));
    }

    /**
     * 按下并释放指定键
     *
     * @param keyCode 键盘键码
     */
    default void keyPress(int keyCode) {
        execute(WindowOperation.press(keyCode));
    }

    /**
     * 执行快捷键组合
     *
     * @param keyCodes 键盘键码序列
     * @throws IllegalArgumentException 如果keyCodes为空
     */
    default void hotkey(int... keyCodes) {
        execute(WindowOperation.hotkey(keyCodes));
    }

    /**
     * 延迟执行
     *
     * @param milliseconds 延迟毫秒数
     * @throws IllegalArgumentException 如果milliseconds为负数
     */
    default void sleep(long milliseconds) {
        execute(WindowOperation.delay(milliseconds));
    }

    /**
     * 拖拽操作
     *
     * @param fromX 起点X坐标
     * @param fromY 起点Y坐标
     * @param toX 终点X坐标
     * @param toY 终点Y坐标
     */
    default void drag(int fromX, int fromY, int toX, int toY) {
        executeSequence(
                WindowOperation.gameMove(fromX, fromY),
                WindowOperation.delay(50),
                WindowOperation.pressMouse(1),
                WindowOperation.delay(100),
                WindowOperation.gameMove(toX, toY),
                WindowOperation.delay(50),
                WindowOperation.releaseMouse(1)
        );
    }

    // ========== ActionBuilder 支持 ==========

    /**
     * 创建动作构建器
     *
     * @return 动作构建器实例
     */
    default ActionBuilder actions() {
        return ActionBuilder.on(this);
    }

    // ========== 生命周期管理 ==========

    /**
     * 启动窗口处理线程
     */
    void start();

    /**
     * 关闭窗口和所有资源
     */
    void shutdown();

    /**
     * 检查窗口处理是否正在运行
     *
     * @return 如果正在运行返回true，否则返回false
     */
    boolean isRunning();

    /**
     * 检查窗口是否有效（存在且运行）
     *
     * @return 如果窗口有效返回true，否则返回false
     */
    boolean isValid();

    /**
     * 等待窗口终止
     *
     * @param timeout 超时时间
     * @param unit 时间单位
     * @return 如果在超时前终止返回true，否则返回false
     * @throws InterruptedException 如果等待过程中被中断
     */
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
}